package org.myOrg.spetrum.Driver;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;

import org.myOrg.spetrum.combination.Tuple;
import org.myOrg.spetrum.io.InputManager;
import org.myOrg.spetrum.io.InputManagerImplement;
import org.myOrg.spetrum.io.OutputManager;
import org.myOrg.spetrum.io.OutputManagerImplement;
import org.myOrg.spetrum.spectrumStruct.Spectrum;
import org.myOrg.spetrum.spectrumStruct.SpectrumFactory;
import org.myOrg.spetrum.testObject.TestSuite;
import org.myOrg.spetrum.testRun.TestRun;
import org.myOrg.spetrum.testRun.TestRunBugMode;
import org.myOrg.spetrum.util.Message;
import org.myOrg.spetrum.util.MessageImplement;
import org.myOrg.spetrum.util.MessageMangement;
import org.myOrg.spetrum.util.MessageMangementImplement;
import org.myOrg.spetrum.util.OverallFactory;
import org.myOrg.spetrum.util.Reciver;
import org.myOrg.spetrum.util.Sender;
import org.myOrg.spetrum.util.Transform;

public class Driver implements Reciver, Sender {
	private InputManager inputManager;
	private OutputManager outputManager;
	private TestRun testRun;
	private List<Tuple> bugMode;

	private SpectrumUnion spectrums;
	private int alorgrithm;
	private TestSuite wrongTests;
	private TestSuite rightTests;
	private int[] param;

	MessageMangement mangerment;

	public Driver() {
		init();
		this.register(MessageMangementImplement.GETINPUTPATH,
				OverallFactory.getMessageManger());
		this.register(MessageMangementImplement.RUN,
				OverallFactory.getMessageManger());
		this.register(MessageMangementImplement.ADDBUGMODEL,
				OverallFactory.getMessageManger());
		this.register(MessageMangementImplement.DELETEBUGMODEL,
				OverallFactory.getMessageManger());
		this.register(MessageMangementImplement.CHANGEALOGRITHM,
				OverallFactory.getMessageManger());
		this.register(MessageMangementImplement.GETOUTPUTPATH,
				OverallFactory.getMessageManger());

		this.setMessageMangement(OverallFactory.getMessageManger());
	}

	public InputManager getInput() {
		return inputManager;
	}

	public TestRun getRun() {
		return testRun;
	}

	public void init() {
		inputManager = new InputManagerImplement();
		outputManager = new OutputManagerImplement();
		alorgrithm = SpectrumFactory.BASE;
		testRun = new TestRunBugMode();
		bugMode = new ArrayList<Tuple>();
		spectrums = new SpectrumUnion();

	}

	public void clear() {
		bugMode.clear();
	}

	public void setInputPath(String path) {
		this.clear();
		inputManager.deal(path);

		Message msg = new MessageImplement(this,
				MessageMangementImplement.READOVER, inputManager);
		sendMessage(msg);

		if (!inputManager.isFormatPass())
			return;
		this.wrongTests = inputManager.getWrongSuite();
		this.rightTests = inputManager.getRightSuite();
		this.param = inputManager.getParam();

	}

	public void run() {
		((TestRunBugMode) testRun).setBugMode(bugMode);

		if (alorgrithm < SpectrumFactory.ALORGRITMNUM) {
			Spectrum spectrum = runOneAlogrithm(alorgrithm);
			Message msg = new MessageImplement(this,
					MessageMangementImplement.RUNOVER, spectrum);
			sendMessage(msg);
		} else {
			Iterator<Entry<Integer, Spectrum>> entry = spectrums.itertor();
			while (entry.hasNext()) {
				runOneAlogrithm(entry.next().getKey().intValue());
			}
			Message msg = new MessageImplement(this,
					MessageMangementImplement.RUNOVER, spectrums);
			sendMessage(msg);
		}
	}

	private Spectrum runOneAlogrithm(int alorgrithm) {
		Spectrum spectrum = spectrums.getSpectrum(alorgrithm);
		spectrum.clear();
		spectrum.setInput(param, wrongTests, rightTests);
		spectrum.setRun(testRun);
		spectrum.run();
		return spectrum;
	}

	@Override
	public void register(int messageType, MessageMangement messageManger) {
		// TODO Auto-generated method stub
		messageManger.register(this, messageType);
	}

	@Override
	public void handleMessage(Message msg) {
		// TODO Auto-generated method stub
		if (msg.getType() == MessageMangementImplement.GETINPUTPATH) {
			this.setInputPath((String) msg.getInfo());
		} else if (msg.getType() == MessageMangementImplement.RUN) {
			this.run();
		} else if (msg.getType() == MessageMangementImplement.ADDBUGMODEL) {
			this.bugMode.add(Transform.vectorToTuple((int[]) msg.getInfo()));
		} else if (msg.getType() == MessageMangementImplement.DELETEBUGMODEL) {
			this.bugMode.remove(((Integer) msg.getInfo()).intValue());
			if (this.bugMode.isEmpty()) {
				Message message = new MessageImplement(this,
						MessageMangementImplement.NOBUGMODEL, null);
				sendMessage(message);
			}
		} else if (msg.getType() == MessageMangementImplement.CHANGEALOGRITHM) {
			this.alorgrithm = ((Integer) msg.getInfo()).intValue();
		} else if (msg.getType() == MessageMangementImplement.GETOUTPUTPATH) {
			if (this.alorgrithm < SpectrumFactory.ALORGRITMNUM) {
				outputManager.outputSpectrum(spectrums.getSpectrum(alorgrithm),
						(String) msg.getInfo());
			} else {
				outputManager.outputSpectrumUnion(spectrums,
						(String) msg.getInfo());
			}

		}
	}

	@Override
	public void sendMessage(Message msg) {
		// TODO Auto-generated method stub
		mangerment.dispatchMeesage(msg);
	}

	@Override
	public void setMessageMangement(MessageMangement mangerment) {
		// TODO Auto-generated method stub
		this.mangerment = mangerment;
	}

}
